-----------------------------------------------------------------------
--
-- This was originally written by Blizzard but was removed in beta
-- during an update.
-- I recovered these files and modified them so they will work
-- in current versions of WoTLK.
-- Any changes I have made would have (Xabora)
-- in the comment lines or the hyphen borders.
--
-----------------------------------------------------------------------
-- Move these globals into a section where we can alter the limits
-- Updated globals with values for options panel (OPT_[NAME])
-----------------------------------------------------------------------
local L = LibStub("AceLocale-3.0"):GetLocale("ClassThreatMeter")
ThreatMeter_Saved = {
	NUM_THREAT_BARS = 5; -- Number to Display
	OPT_PET = 0; -- Show Pets
	OPT_PORT = 1; -- Show Portaits
	OPT_SIZE_X = 100; -- Size X Axis
	OPT_TIP = 2; -- Show Tooltip on hover (Percent)
	OPT_INLINE = 0; -- Show Threat Percent or RAW Inline
	OPT_BCKDRP = 0; -- Show Backdrop on 1
};

-- Temp Values
NUMTHREATBARS = 5;
OPTPET = 0
OPTPORT = 1;
OPTSIZEX = 100;
OPTTIP = 2;
OPTINLINE = 0;
OPTBCKDRP = 0;

--Combat Timer (For TPS/M)
local TMR_CMBT = 0; 
-- Maximum Threatbars allowed (Fixes ghost bars)
local MAX_BARS = 10; --can handle 15 max, but saving for later.
-----------------------------------------------------------------------

local function ThreatMeter_FindTableIndex(threatTable, isTanking, percentage)
	-- Do an insertion sort based on threat percentage
	for i = 1, threatTable.n do
		local t = threatTable[i];
		if ( isTanking or (not t.isTanking and (percentage > t.percentage)) ) then
			if ( threatTable.n < NUMTHREATBARS ) then
				threatTable.n = threatTable.n + 1;
			end
			t = threatTable[threatTable.n];
			for j = threatTable.n-1, i, -1 do
				threatTable[j+1] = threatTable[j];
			end
			threatTable[i] = t;
			return i;
		end
	end
	if ( threatTable.n < NUMTHREATBARS ) then
		threatTable.n = threatTable.n + 1;
		return threatTable.n;
	end	
end

function ThreatMeter_InsertTarget(threatTable, target, unit)
	local isTanking, status, percentage, relPercent, threatValue = UnitDetailedThreatSituation(target, unit);
	--Show threat at lowest value (XABORA)
	if ( percentage and percentage > 0.1 ) then
		local index = ThreatMeter_FindTableIndex(threatTable, isTanking, percentage, threatValue);
		if ( index ) then
			local t = threatTable[index];
			t.unit = target;
			t.name = UnitName(target);
			t.isTanking = isTanking;
			t.percentage = percentage;
			t.threatValue = threatValue; --added
			t.r, t.g, t.b = GetThreatStatusColor(status);
		end
	end
end

function ThreatMeter_SetStatusBarIcon(icon, unit)
	if ( UnitIsUnit(unit, "player") ) then
		--Call the Portrait function (XABORA)
		ThreatMeterPortraits(icon, unit, OPTPORT);
	else
		local index = GetRaidTargetIndex(unit);
		if ( index ) then
			icon:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons");
			SetRaidTargetIconTexture(icon, index);
			icon:SetVertexColor(1.0, 1.0, 1.0);
			icon:Show();
		elseif ( strfind(unit, "pet", 1, true) ) then
-----------------------------------------------------------------------
-- Check if player has portrait enabled
-----------------------------------------------------------------------
			ThreatMeterPortraits(icon, unit, OPTPET);
		else
			ThreatMeterPortraits(icon, unit, OPTPORT);
-----------------------------------------------------------------------
		end
	end
end

function ThreatMeterPortraits(icon, unit, val)
	if ( val == 1 ) then
		SetPortraitTexture(icon, unit);
		icon:SetTexCoord(0, 1, 0, 1);
		icon:SetVertexColor(1.0, 1.0, 1.0);
		icon:Show();
	else
		local class, fileName = UnitClassBase(unit);
		icon:SetTexture("Interface\\Minimap\\ObjectIcons");
		icon:SetTexCoord(0.75, 0.875, 0.5, 1.0);
		local color = RAID_CLASS_COLORS[fileName];
		--fix for an extremely rare nil color bug
		if (color == nil) then icon:SetVertexColor(0,0,0);
		else icon:SetVertexColor(color.r, color.g, color.b); end
		icon:Show();
	end
end

function ThreatMeter_Update(self)
-----------------------------------------------------------------------
-- Lets rem this out so we can get this to work.
-- showThreatMeter was removed in a patch (Xabora)
-----------------------------------------------------------------------
	--if ( not IsThreatWarningEnabled() or not GetCVarBool("showThreatMeter") ) then
	--	self:Hide();
	--	return;
	--end
-----------------------------------------------------------------------

	-- See whether we should show the threat frame
	local unit;
	if ( UnitCanAttack("player", self.startingUnit) ) then
		unit = self.startingUnit;
	elseif ( UnitCanAttack("player", self.startingUnit.."target") ) then
		unit = self.startingUnit.."target";
	else
		self:Hide();
		return;
	end

	--Update Framesize (XABORA)
	self:SetWidth(OPTSIZEX);
	self.name:SetWidth(OPTSIZEX-8);

	-- Add each target on the unit's threat list
	local threatTable = self.threatTable;
	threatTable.n = 0;
	if ( GetNumRaidMembers() > 0 ) then
		for i=1, MAX_RAID_MEMBERS do
			ThreatMeter_InsertTarget(threatTable, "raid"..i, unit);
			ThreatMeter_InsertTarget(threatTable, "raidpet"..i, unit);
		end
	elseif ( GetNumPartyMembers() > 0 ) then
		for i=1, MAX_PARTY_MEMBERS do
			ThreatMeter_InsertTarget(threatTable, "party"..i, unit);
			ThreatMeter_InsertTarget(threatTable, "partypet"..i, unit);
		end
		ThreatMeter_InsertTarget(threatTable, "player", unit);
		ThreatMeter_InsertTarget(threatTable, "pet", unit);
	else
		ThreatMeter_InsertTarget(threatTable, "player", unit);
		ThreatMeter_InsertTarget(threatTable, "pet", unit);
	end

	-- Hide the UI if there's no threat list
	if ( threatTable.n == 0 ) then
		self:Hide();
		return;
	end

	-- Show the status bars for the threat list
	local prefix = self:GetName();
	local tooltip = self.tooltip;
	for i=1, threatTable.n do
		local entry = threatTable[i];
		local statusBar = getglobal(prefix.."StatusBar"..i);
		local statusBarThreatText = getglobal(prefix.."StatusBar"..i.."Threat");
		if ( statusBar ) then
			--Update Framesize (XABORA)
			statusBar:SetWidth(OPTSIZEX-10);
				if ( OPTBCKDRP == 1 ) then
					statusBar:SetBackdropColor(0.2,0.2,0.2,0.8);
				else
					statusBar:SetBackdropColor(0.2,0.2,0.2,0.0);
				end
			statusBar.entry = entry;
			statusBar.name:SetText(entry.name);

			ThreatMeter_SetStatusBarIcon(statusBar.icon, entry.unit);
			statusBar:SetValue(entry.percentage);
			statusBar:SetStatusBarColor(entry.r, entry.g, entry.b);
			--Pass data to Threat Display (Xabora)
			ThreatMeterUpdateDisplay(statusBarThreatText, entry, OPTINLINE);
			statusBar:Show();
			
			if (tooltip.owner == statusBar and OPTTIP >= 1) then
				ThreatMeterStatusBar_UpdateTooltip(tooltip, entry);
			end
		end
	end
	for i = threatTable.n+1, MAX_BARS do
		local statusBar = getglobal(prefix.."StatusBar"..i);
		if ( statusBar ) then
			statusBar:Hide();
		end
	end

	-- Show the player's status
	self.name:SetText(UnitName(unit));
	local index = GetRaidTargetIndex(unit);
	if ( index ) then
		SetRaidTargetIconTexture(self.icon, index);
		self.icon:Show();
	else
		self.icon:Hide();
	end
	local status = UnitThreatSituation("player", unit);
	self:SetBackdropBorderColor(GetThreatStatusColor(status));
	self:SetBackdropColor(GetThreatStatusColor(status));

	-- We're done!
	self.unit = unit;

-----------------------------------------------------------------------
-- Update 8 times a second, every half a second was too slow (Xabora)
-- Changed from 10 due to increased code to releave system resources.
-----------------------------------------------------------------------
	self.timer = 0.125;	-- Update every 1/2 second
-----------------------------------------------------------------------
	TMR_CMBT = ( TMR_CMBT + 0.125 ); -- update time in-combat
	self:Show();
end

function ThreatMeter_OnLoad(self, unit)
	--MAX_BARS = 10;
	self:RegisterForDrag("LeftButton");
	self.UpdateTooltip = ThreatMeter_UpdateTooltip;

	if ( unit == "target" ) then
		self:RegisterEvent("PLAYER_TARGET_CHANGED");
	elseif ( unit == "focus" ) then
		self:RegisterEvent("PLAYER_FOCUS_CHANGED");
	end
	self:RegisterEvent("UNIT_TARGET");
	self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE");
	self:RegisterEvent("RAID_TARGET_UPDATE");
-----------------------------------------------------------------------
-- Register new events
-----------------------------------------------------------------------
	self:RegisterEvent("UNIT_THREAT_LIST_UPDATE");
	self:RegisterEvent("PLAYER_REGEN_ENABLED");
	self:RegisterEvent("PLAYER_REGEN_DISABLED");
	self:RegisterEvent("VARIABLES_LOADED");
-----------------------------------------------------------------------

	local prefix = self:GetName();
	self.name = _G[prefix.."Name"];
	self.icon = _G[prefix.."Icon"];
	self.tooltip = _G[prefix.."Tooltip"];
	self.tooltip.text = _G[prefix.."TooltipText"];
	self.threatTable = {};
	for i = 1, MAX_BARS do
		self.threatTable[i] = {};
	end
	self.startingUnit = unit;
end

function ThreatMeter_OnEvent(self, event, ...)
	if ( event == "PLAYER_TARGET_CHANGED" or
	     event == "PLAYER_FOCUS_CHANGED" or (event == "UNIT_TARGET" and (...) == self.startingUnit) ) 	then
		ThreatMeter_Update(self);
	else
		-- If we're visible, update on the next frame
		self.timer = nil;
	end
-----------------------------------------------------------------------
-- Hide the Meters when out of combat / Show them on Combat
-----------------------------------------------------------------------
	if ( event == "PLAYER_REGEN_ENABLED" ) then
		self:Hide();
		TMR_CMBT = 0;
	elseif ( event == "PLAYER_REGEN_DISABLED" ) then
		self:Show();
		TMR_CMBT = 0; --prevents players messing with the timer
	end

-- Fix for Hunter Display issue & late combat engagement
	if ( event == "UNIT_THREAT_LIST_UPDATE" and UnitIsPlayer("target") == nil ) then
		self:Show();
		ThreatMeter_Update(self);
		--local prefix = self:GetName();
		--DEFAULT_CHAT_FRAME:AddMessage(prefix..": Target is NPC. Trigger: UNIT_THREAT_LIST_UPDATE.");
	end
-----------------------------------------------------------------------
	if ( event == "VARIABLES_LOADED" ) then
		if  (ThreatMeter_Saved == nil) then
			ThreatMeter_Saved = {};
			ThreatMeter_Saved.NUM_THREAT_BARS = 5;
			ThreatMeter_Saved.OPT_PET = 0;
			ThreatMeter_Saved.OPT_PORT = 1;
			ThreatMeter_Saved.OPT_SIZE_X = 100;
			ThreatMeter_Saved.OPT_TIP = 2;
			ThreatMeter_Saved.OPT_INLINE = 0;
		end

		-- Force these to into temp data for Options
		NUMTHREATBARS = ThreatMeter_Saved.NUM_THREAT_BARS;
		OPTPET = ThreatMeter_Saved.OPT_PET;
		OPTPORT = ThreatMeter_Saved.OPT_PORT;
		OPTSIZEX = ThreatMeter_Saved.OPT_SIZE_X;
		OPTTIP = ThreatMeter_Saved.OPT_TIP;
		OPTINLINE = ThreatMeter_Saved.OPT_INLINE;
		OPTBCKDRP = ThreatMeter_Saved.OPT_BCKDRP;
	end
end

function ThreatMeter_OnUpdate(self, elapsed)
	if ( not self.timer or self.timer < elapsed ) then
		ThreatMeter_Update(self);
	else
		self.timer = self.timer - elapsed;
	end
end

function ThreatMeter_OnEnter(self)
	ThreatMeter_UpdateTooltip(self);
end

function ThreatMeter_OnLeave(self)
	GameTooltip:Hide();
end

function ThreatMeter_UpdateTooltip(self)
	GameTooltip_SetDefaultAnchor(GameTooltip, self);
	GameTooltip:SetUnit(self.unit);
end

function ThreatMeterStatusBar_OnLoad(self)
	self:SetMinMaxValues(0, 100);
	self.name = getglobal(self:GetName().."Name");
	self.icon = getglobal(self:GetName().."Icon");
end

function ThreatMeterStatusBar_OnEnter(self)
		if ( not IsMouseButtonDown() and OPTTIP >= 1 ) then
			local tooltip = self:GetParent().tooltip;
			tooltip.owner = self;
			ThreatMeterStatusBar_UpdateTooltip(tooltip, self.entry);
			tooltip:SetPoint("LEFT", self, "RIGHT");
			tooltip:Show();
		end
end

function ThreatMeterStatusBar_OnLeave(self)
	local tooltip = self:GetParent().tooltip;
	tooltip.owner = nil;
	tooltip:Hide();
end

function ThreatMeterStatusBar_UpdateTooltip(tooltip, entry)
	--Combined with Statusbar threat
	ThreatMeterUpdateDisplay(tooltip.text, entry, OPTTIP);
	tooltip:SetBackdropColor(entry.r, entry.g, entry.b);
end

function ThreatMeterUpdateDisplay(disptext, entry, val)
-----------------------------------------------------------------------
--Threat is compressed with no decimal on the trailing 00s
--Dividing by 100 we get the actual threat.
--Thanks to Peons/Parsous (Madoran) for finding this.
-----------------------------------------------------------------------
	if ( val == 1 ) then
		--Easy Threat Compares! (XABORA)
		if ( entry.g == 0 and entry.b == 0 ) then
			disptext:SetText(L["坦克"]);
		elseif ( entry.g >= 0 and entry.b == 0 ) then
			disptext:SetText(L["获取"]);
		elseif ( entry.r >= 0.8 and entry.b <= 0.5 ) then
			disptext:SetText(L["失去"]);
		elseif ( entry.r == entry.b ) then
			disptext:SetText(L["安全"]);
		else
			disptext:SetText(L["错误"]);
		end
	elseif ( val == 2 ) then
		disptext:SetFormattedText("%d%%", math.floor(entry.percentage));
	elseif ( val == 3 ) then
		if ( entry.threatValue > 100000000 ) then
			disptext:SetFormattedText("%.2f".."M", (entry.threatValue / 100000000));
		else
			disptext:SetFormattedText("%.2f".."K", (entry.threatValue / 100000));
		end
	elseif ( val == 4 ) then
		disptext:SetFormattedText("%.2f", (entry.threatValue / 100));
	elseif ( val == 5 ) then
		--Threat Per Second
		if ( ( ( entry.threatValue / 100000000) / TMR_CMBT ) > 0.99 ) then
			disptext:SetFormattedText("%.2f".."M TPS", ((entry.threatValue / 100000000) / TMR_CMBT));
		else
			disptext:SetFormattedText("%.2f".."K TPS", ((entry.threatValue / 100000) / TMR_CMBT));
		end
	elseif ( val == 6 ) then
		--Threat Per Min
		if ( entry.threatValue > 100000000 ) then
			disptext:SetFormattedText("%.2f".."M TPM", ((entry.threatValue / 100000000) / ( TMR_CMBT / 60 )));
		else
			disptext:SetFormattedText("%.1f".."K TPM", ((entry.threatValue / 100000) / ( TMR_CMBT / 60 )));
		end
	else
		--Set text to nil if disabled (XABORA)
		disptext:SetText(nil);
	end

end